﻿// This file is part of libnoise-dotnet.
//
// libnoise-dotnet is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// libnoise-dotnet is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with libnoise-dotnet.  If not, see <http://www.gnu.org/licenses/>.
// 
// From the original Jason Bevins's Libnoise (http://libnoise.sourceforge.net)

// Specifies the version of the coherent-noise functions to use.

// - define LIBNOISE_VERSION_2 to use the current version.
// - define LIBNOISE_VERSION_1 to use the flawed version from the original version of libnoise.
//
// If your application requires coherent-noise values that were generated by
// an earlier version of libnoise, change this constant to the appropriate
// value and recompile libnoise.
//#define LIBNOISE_VERSION_1;
#define LIBNOISE_VERSION_2

using Graphics.Tools.Noise;

namespace Graphics.Tools.Noise.Primitive {

	/// <summary>
	/// A gradient noise generator. The Jason Bevins's Libnoise ported in c#
	/// </summary>
	public class BevinsGradient :PrimitiveModule, IModule3D {

		#region Constants
		// These constants control certain parameters that all coherent-noise
		// functions require.
#if LIBNOISE_VERSION_2

		// Constants used by the current version of libnoise.
		public const int X_NOISE_GEN = 1619;
		public const int Y_NOISE_GEN = 31337;
		public const int Z_NOISE_GEN = 6971;
		public const int SEED_NOISE_GEN = 1013;
		public const int SHIFT_NOISE_GEN = 8;

#else

		// Constants used by the original version of libnoise.
		// Because X_NOISE_GEN is not relatively prime to the other values, and
		// Z_NOISE_GEN is close to 256 (the number of random gradient vectors),
		// patterns show up in high-frequency coherent noise.
		public const int X_NOISE_GEN = 1;
		public const int Y_NOISE_GEN = 31337;
		public const int Z_NOISE_GEN = 263;
		public const int SEED_NOISE_GEN = 1013;
		public const int SHIFT_NOISE_GEN = 13;

#endif
		#endregion

		#region Fields

		// A table of 256 random normalized vectors.  Each row is an (x, y, z, 0)
		// coordinate.  The 0 is used as padding so we can use bit shifts to index
		// any row in the table.  These vectors have an even statistical
		// distribution, which improves the quality of the coherent noise
		// generated by these vectors.  For more information, see "GPU Gems",
		// Chapter 5 - Implementing Improved Perlin Noise by Ken Perlin,
		// specifically page 76.
		protected static float[] _randomVectors =  {
-0.763874f, -0.596439f, -0.246489f, 0.0f,
            0.396055f, 0.904518f, -0.158073f, 0.0f,
            -0.499004f, -0.8665f, -0.0131631f, 0.0f,
            0.468724f, -0.824756f, 0.316346f, 0.0f,
            0.829598f, 0.43195f, 0.353816f, 0.0f,
            -0.454473f, 0.629497f, -0.630228f, 0.0f,
            -0.162349f, -0.869962f, -0.465628f, 0.0f,
            0.932805f, 0.253451f, 0.256198f, 0.0f,
            -0.345419f, 0.927299f, -0.144227f, 0.0f,
            -0.715026f, -0.293698f, -0.634413f, 0.0f,
            -0.245997f, 0.717467f, -0.651711f, 0.0f,
            -0.967409f, -0.250435f, -0.037451f, 0.0f,
            0.901729f, 0.397108f, -0.170852f, 0.0f,
            0.892657f, -0.0720622f, -0.444938f, 0.0f,
            0.0260084f, -0.0361701f, 0.999007f, 0.0f,
            0.949107f, -0.19486f, 0.247439f, 0.0f,
            0.471803f, -0.807064f, -0.355036f, 0.0f,
            0.879737f, 0.141845f, 0.453809f, 0.0f,
            0.570747f, 0.696415f, 0.435033f, 0.0f,
            -0.141751f, -0.988233f, -0.0574584f, 0.0f,
            -0.58219f, -0.0303005f, 0.812488f, 0.0f,
            -0.60922f, 0.239482f, -0.755975f, 0.0f,
            0.299394f, -0.197066f, -0.933557f, 0.0f,
            -0.851615f, -0.220702f, -0.47544f, 0.0f,
            0.848886f, 0.341829f, -0.403169f, 0.0f,
            -0.156129f, -0.687241f, 0.709453f, 0.0f,
            -0.665651f, 0.626724f, 0.405124f, 0.0f,
            0.595914f, -0.674582f, 0.43569f, 0.0f,
            0.171025f, -0.509292f, 0.843428f, 0.0f,
            0.78605f, 0.536414f, -0.307222f, 0.0f,
            0.18905f, -0.791613f, 0.581042f, 0.0f,
            -0.294916f, 0.844994f, 0.446105f, 0.0f,
            0.342031f, -0.58736f, -0.7335f, 0.0f,
            0.57155f, 0.7869f, 0.232635f, 0.0f,
            0.885026f, -0.408223f, 0.223791f, 0.0f,
            -0.789518f, 0.571645f, 0.223347f, 0.0f,
            0.774571f, 0.31566f, 0.548087f, 0.0f,
            -0.79695f, -0.0433603f, -0.602487f, 0.0f,
            -0.142425f, -0.473249f, -0.869339f, 0.0f,
            -0.0698838f, 0.170442f, 0.982886f, 0.0f,
            0.687815f, -0.484748f, 0.540306f, 0.0f,
            0.543703f, -0.534446f, -0.647112f, 0.0f,
            0.97186f, 0.184391f, -0.146588f, 0.0f,
            0.707084f, 0.485713f, -0.513921f, 0.0f,
            0.942302f, 0.331945f, 0.043348f, 0.0f,
            0.499084f, 0.599922f, 0.625307f, 0.0f,
            -0.289203f, 0.211107f, 0.9337f, 0.0f,
            0.412433f, -0.71667f, -0.56239f, 0.0f,
            0.87721f, -0.082816f, 0.47291f, 0.0f,
            -0.420685f, -0.214278f, 0.881538f, 0.0f,
            0.752558f, -0.0391579f, 0.657361f, 0.0f,
            0.0765725f, -0.996789f, 0.0234082f, 0.0f,
            -0.544312f, -0.309435f, -0.779727f, 0.0f,
            -0.455358f, -0.415572f, 0.787368f, 0.0f,
            -0.874586f, 0.483746f, 0.0330131f, 0.0f,
            0.245172f, -0.0838623f, 0.965846f, 0.0f,
            0.382293f, -0.432813f, 0.81641f, 0.0f,
            -0.287735f, -0.905514f, 0.311853f, 0.0f,
            -0.667704f, 0.704955f, -0.239186f, 0.0f,
            0.717885f, -0.464002f, -0.518983f, 0.0f,
            0.976342f, -0.214895f, 0.0240053f, 0.0f,
            -0.0733096f, -0.921136f, 0.382276f, 0.0f,
            -0.986284f, 0.151224f, -0.0661379f, 0.0f,
            -0.899319f, -0.429671f, 0.0812908f, 0.0f,
            0.652102f, -0.724625f, 0.222893f, 0.0f,
            0.203761f, 0.458023f, -0.865272f, 0.0f,
            -0.030396f, 0.698724f, -0.714745f, 0.0f,
            -0.460232f, 0.839138f, 0.289887f, 0.0f,
            -0.0898602f, 0.837894f, 0.538386f, 0.0f,
            -0.731595f, 0.0793784f, 0.677102f, 0.0f,
            -0.447236f, -0.788397f, 0.422386f, 0.0f,
            0.186481f, 0.645855f, -0.740335f, 0.0f,
            -0.259006f, 0.935463f, 0.240467f, 0.0f,
            0.445839f, 0.819655f, -0.359712f, 0.0f,
            0.349962f, 0.755022f, -0.554499f, 0.0f,
            -0.997078f, -0.0359577f, 0.0673977f, 0.0f,
            -0.431163f, -0.147516f, -0.890133f, 0.0f,
            0.299648f, -0.63914f, 0.708316f, 0.0f,
            0.397043f, 0.566526f, -0.722084f, 0.0f,
            -0.502489f, 0.438308f, -0.745246f, 0.0f,
            0.0687235f, 0.354097f, 0.93268f, 0.0f,
            -0.0476651f, -0.462597f, 0.885286f, 0.0f,
            -0.221934f, 0.900739f, -0.373383f, 0.0f,
            -0.956107f, -0.225676f, 0.186893f, 0.0f,
            -0.187627f, 0.391487f, -0.900852f, 0.0f,
            -0.224209f, -0.315405f, 0.92209f, 0.0f,
            -0.730807f, -0.537068f, 0.421283f, 0.0f,
            -0.0353135f, -0.816748f, 0.575913f, 0.0f,
            -0.941391f, 0.176991f, -0.287153f, 0.0f,
            -0.154174f, 0.390458f, 0.90762f, 0.0f,
            -0.283847f, 0.533842f, 0.796519f, 0.0f,
            -0.482737f, -0.850448f, 0.209052f, 0.0f,
            -0.649175f, 0.477748f, 0.591886f, 0.0f,
            0.885373f, -0.405387f, -0.227543f, 0.0f,
            -0.147261f, 0.181623f, -0.972279f, 0.0f,
            0.0959236f, -0.115847f, -0.988624f, 0.0f,
            -0.89724f, -0.191348f, 0.397928f, 0.0f,
            0.903553f, -0.428461f, -0.00350461f, 0.0f,
            0.849072f, -0.295807f, -0.437693f, 0.0f,
            0.65551f, 0.741754f, -0.141804f, 0.0f,
            0.61598f, -0.178669f, 0.767232f, 0.0f,
            0.0112967f, 0.932256f, -0.361623f, 0.0f,
            -0.793031f, 0.258012f, 0.551845f, 0.0f,
            0.421933f, 0.454311f, 0.784585f, 0.0f,
            -0.319993f, 0.0401618f, -0.946568f, 0.0f,
            -0.81571f, 0.551307f, -0.175151f, 0.0f,
            -0.377644f, 0.00322313f, 0.925945f, 0.0f,
            0.129759f, -0.666581f, -0.734052f, 0.0f,
            0.601901f, -0.654237f, -0.457919f, 0.0f,
            -0.927463f, -0.0343576f, -0.372334f, 0.0f,
            -0.438663f, -0.868301f, -0.231578f, 0.0f,
            -0.648845f, -0.749138f, -0.133387f, 0.0f,
            0.507393f, -0.588294f, 0.629653f, 0.0f,
            0.726958f, 0.623665f, 0.287358f, 0.0f,
            0.411159f, 0.367614f, -0.834151f, 0.0f,
            0.806333f, 0.585117f, -0.0864016f, 0.0f,
            0.263935f, -0.880876f, 0.392932f, 0.0f,
            0.421546f, -0.201336f, 0.884174f, 0.0f,
            -0.683198f, -0.569557f, -0.456996f, 0.0f,
            -0.117116f, -0.0406654f, -0.992285f, 0.0f,
            -0.643679f, -0.109196f, -0.757465f, 0.0f,
            -0.561559f, -0.62989f, 0.536554f, 0.0f,
            0.0628422f, 0.104677f, -0.992519f, 0.0f,
            0.480759f, -0.2867f, -0.828658f, 0.0f,
            -0.228559f, -0.228965f, -0.946222f, 0.0f,
            -0.10194f, -0.65706f, -0.746914f, 0.0f,
            0.0689193f, -0.678236f, 0.731605f, 0.0f,
            0.401019f, -0.754026f, 0.52022f, 0.0f,
            -0.742141f, 0.547083f, -0.387203f, 0.0f,
            -0.00210603f, -0.796417f, -0.604745f, 0.0f,
            0.296725f, -0.409909f, -0.862513f, 0.0f,
            -0.260932f, -0.798201f, 0.542945f, 0.0f,
            -0.641628f, 0.742379f, 0.192838f, 0.0f,
            -0.186009f, -0.101514f, 0.97729f, 0.0f,
            0.106711f, -0.962067f, 0.251079f, 0.0f,
            -0.743499f, 0.30988f, -0.592607f, 0.0f,
            -0.795853f, -0.605066f, -0.0226607f, 0.0f,
            -0.828661f, -0.419471f, -0.370628f, 0.0f,
            0.0847218f, -0.489815f, -0.8677f, 0.0f,
            -0.381405f, 0.788019f, -0.483276f, 0.0f,
            0.282042f, -0.953394f, 0.107205f, 0.0f,
            0.530774f, 0.847413f, 0.0130696f, 0.0f,
            0.0515397f, 0.922524f, 0.382484f, 0.0f,
            -0.631467f, -0.709046f, 0.313852f, 0.0f,
            0.688248f, 0.517273f, 0.508668f, 0.0f,
            0.646689f, -0.333782f, -0.685845f, 0.0f,
            -0.932528f, -0.247532f, -0.262906f, 0.0f,
            0.630609f, 0.68757f, -0.359973f, 0.0f,
            0.577805f, -0.394189f, 0.714673f, 0.0f,
            -0.887833f, -0.437301f, -0.14325f, 0.0f,
            0.690982f, 0.174003f, 0.701617f, 0.0f,
            -0.866701f, 0.0118182f, 0.498689f, 0.0f,
            -0.482876f, 0.727143f, 0.487949f, 0.0f,
            -0.577567f, 0.682593f, -0.447752f, 0.0f,
            0.373768f, 0.0982991f, 0.922299f, 0.0f,
            0.170744f, 0.964243f, -0.202687f, 0.0f,
            0.993654f, -0.035791f, -0.106632f, 0.0f,
            0.587065f, 0.4143f, -0.695493f, 0.0f,
            -0.396509f, 0.26509f, -0.878924f, 0.0f,
            -0.0866853f, 0.83553f, -0.542563f, 0.0f,
            0.923193f, 0.133398f, -0.360443f, 0.0f,
            0.00379108f, -0.258618f, 0.965972f, 0.0f,
            0.239144f, 0.245154f, -0.939526f, 0.0f,
            0.758731f, -0.555871f, 0.33961f, 0.0f,
            0.295355f, 0.309513f, 0.903862f, 0.0f,
            0.0531222f, -0.91003f, -0.411124f, 0.0f,
            0.270452f, 0.0229439f, -0.96246f, 0.0f,
            0.563634f, 0.0324352f, 0.825387f, 0.0f,
            0.156326f, 0.147392f, 0.976646f, 0.0f,
            -0.0410141f, 0.981824f, 0.185309f, 0.0f,
            -0.385562f, -0.576343f, -0.720535f, 0.0f,
            0.388281f, 0.904441f, 0.176702f, 0.0f,
            0.945561f, -0.192859f, -0.262146f, 0.0f,
            0.844504f, 0.520193f, 0.127325f, 0.0f,
            0.0330893f, 0.999121f, -0.0257505f, 0.0f,
            -0.592616f, -0.482475f, -0.644999f, 0.0f,
            0.539471f, 0.631024f, -0.557476f, 0.0f,
            0.655851f, -0.027319f, -0.754396f, 0.0f,
            0.274465f, 0.887659f, 0.369772f, 0.0f,
            -0.123419f, 0.975177f, -0.183842f, 0.0f,
            -0.223429f, 0.708045f, 0.66989f, 0.0f,
            -0.908654f, 0.196302f, 0.368528f, 0.0f,
            -0.95759f, -0.00863708f, 0.288005f, 0.0f,
            0.960535f, 0.030592f, 0.276472f, 0.0f,
            -0.413146f, 0.907537f, 0.0754161f, 0.0f,
            -0.847992f, 0.350849f, -0.397259f, 0.0f,
            0.614736f, 0.395841f, 0.68221f, 0.0f,
            -0.503504f, -0.666128f, -0.550234f, 0.0f,
            -0.268833f, -0.738524f, -0.618314f, 0.0f,
            0.792737f, -0.60001f, -0.107502f, 0.0f,
            -0.637582f, 0.508144f, -0.579032f, 0.0f,
            0.750105f, 0.282165f, -0.598101f, 0.0f,
            -0.351199f, -0.392294f, -0.850155f, 0.0f,
            0.250126f, -0.960993f, -0.118025f, 0.0f,
            -0.732341f, 0.680909f, -0.0063274f, 0.0f,
            -0.760674f, -0.141009f, 0.633634f, 0.0f,
            0.222823f, -0.304012f, 0.926243f, 0.0f,
            0.209178f, 0.505671f, 0.836984f, 0.0f,
            0.757914f, -0.56629f, -0.323857f, 0.0f,
            -0.782926f, -0.339196f, 0.52151f, 0.0f,
            -0.462952f, 0.585565f, 0.665424f, 0.0f,
            0.61879f, 0.194119f, -0.761194f, 0.0f,
            0.741388f, -0.276743f, 0.611357f, 0.0f,
            0.707571f, 0.702621f, 0.0752872f, 0.0f,
            0.156562f, 0.819977f, 0.550569f, 0.0f,
            -0.793606f, 0.440216f, 0.42f, 0.0f,
            0.234547f, 0.885309f, -0.401517f, 0.0f,
            0.132598f, 0.80115f, -0.58359f, 0.0f,
            -0.377899f, -0.639179f, 0.669808f, 0.0f,
            -0.865993f, -0.396465f, 0.304748f, 0.0f,
            -0.624815f, -0.44283f, 0.643046f, 0.0f,
            -0.485705f, 0.825614f, -0.287146f, 0.0f,
            -0.971788f, 0.175535f, 0.157529f, 0.0f,
            -0.456027f, 0.392629f, 0.798675f, 0.0f,
            -0.0104443f, 0.521623f, -0.853112f, 0.0f,
            -0.660575f, -0.74519f, 0.091282f, 0.0f,
            -0.0157698f, -0.307475f, -0.951425f, 0.0f,
            -0.603467f, -0.250192f, 0.757121f, 0.0f,
            0.506876f, 0.25006f, 0.824952f, 0.0f,
            0.255404f, 0.966794f, 0.00884498f, 0.0f,
            0.466764f, -0.874228f, -0.133625f, 0.0f,
            0.475077f, -0.0682351f, -0.877295f, 0.0f,
            -0.224967f, -0.938972f, -0.260233f, 0.0f,
            -0.377929f, -0.814757f, -0.439705f, 0.0f,
            -0.305847f, 0.542333f, -0.782517f, 0.0f,
            0.26658f, -0.902905f, -0.337191f, 0.0f,
            0.0275773f, 0.322158f, -0.946284f, 0.0f,
            0.0185422f, 0.716349f, 0.697496f, 0.0f,
            -0.20483f, 0.978416f, 0.0273371f, 0.0f,
            -0.898276f, 0.373969f, 0.230752f, 0.0f,
            -0.00909378f, 0.546594f, 0.837349f, 0.0f,
            0.6602f, -0.751089f, 0.000959236f, 0.0f,
            0.855301f, -0.303056f, 0.420259f, 0.0f,
            0.797138f, 0.0623013f, -0.600574f, 0.0f,
            0.48947f, -0.866813f, 0.0951509f, 0.0f,
            0.251142f, 0.674531f, 0.694216f, 0.0f,
            -0.578422f, -0.737373f, -0.348867f, 0.0f,
            -0.254689f, -0.514807f, 0.818601f, 0.0f,
            0.374972f, 0.761612f, 0.528529f, 0.0f,
            0.640303f, -0.734271f, -0.225517f, 0.0f,
            -0.638076f, 0.285527f, 0.715075f, 0.0f,
            0.772956f, -0.15984f, -0.613995f, 0.0f,
            0.798217f, -0.590628f, 0.118356f, 0.0f,
            -0.986276f, -0.0578337f, -0.154644f, 0.0f,
            -0.312988f, -0.94549f, 0.0899272f, 0.0f,
            -0.497338f, 0.178325f, 0.849032f, 0.0f,
            -0.101136f, -0.981014f, 0.165477f, 0.0f,
            -0.521688f, 0.0553434f, -0.851339f, 0.0f,
            -0.786182f, -0.583814f, 0.202678f, 0.0f,
            -0.565191f, 0.821858f, -0.0714658f, 0.0f,
            0.437895f, 0.152598f, -0.885981f, 0.0f,
            -0.92394f, 0.353436f, -0.14635f, 0.0f,
            0.212189f, -0.815162f, -0.538969f, 0.0f,
            -0.859262f, 0.143405f, -0.491024f, 0.0f,
            0.991353f, 0.112814f, 0.0670273f, 0.0f,
            0.0337884f, -0.979891f, -0.196654f, 0.0f  
        };

		#endregion

		#region Ctor/Dtor

		/// <summary>
		/// 0-args constructor
		/// </summary>
		public BevinsGradient()
			: this(DEFAULT_SEED, DEFAULT_QUALITY) {

		}//end BevinsGradient

		/// <summary>
		/// Create a new BevinsGradientNoise with given values
		/// </summary>
		/// <param name="seed"></param>
		/// <param name="quality"></param>
		public BevinsGradient(int seed, NoiseQuality quality) {
			
			_seed = seed;
			_quality = quality;

		}//end BevinsGradient

		#endregion

		#region IModule3D Members

		/// <summary>
		/// Generates an output value given the coordinates of the specified input value.
		/// </summary>
		/// <param name="x">The input coordinate on the x-axis.</param>
		/// <param name="y">The input coordinate on the y-axis.</param>
		/// <param name="z">The input coordinate on the z-axis.</param>
		/// <returns>The resulting output value.</returns>
		public float GetValue(float x, float y, float z) {
			return GradientCoherentNoise3D(x, y, z, _seed, _quality);
		}//end GetValue

		#endregion

		#region GradientCoherentNoise3D

		/// <summary>
		/// Generates a gradient-coherent-noise value from the coordinates of a
		/// three-dimensional input value.
		///
		/// The return value ranges from -1.0 to +1.0.
		///
		/// For an explanation of the difference between <i>gradient</i> noise and
		/// <i>value</i> noise, see the comments for the GradientNoise3D() function.
		/// </summary>
		/// <param name="x">The x coordinate of the input value</param>
		/// <param name="y">The y coordinate of the input value</param>
		/// <param name="z">The z coordinate of the input value</param>
		/// <param name="seed">seed The random number seed</param>
		/// <param name="quality">The quality of the coherent-noise</param>
		/// <returns>The generated gradient-coherent-noise value</returns>
		public float GradientCoherentNoise3D(float x, float y, float z, long seed, NoiseQuality quality) {

			// Create a unit-length cube aligned along an integer boundary.  
			// This cube surrounds the input point.
			int x0 = (x > 0.0 ? (int)x: (int)x - 1); // FastFloor()
			int x1 = x0 + 1;

			int y0 = (y > 0.0 ? (int)y: (int)y - 1);
			int y1 = y0 + 1;

			int z0 = (z > 0.0 ? (int)z: (int)z - 1);
			int z1 = z0 + 1;

			// Map the difference between the coordinates of the input value and the
			// coordinates of the cube's outer-lower-left vertex onto an S-curve.
			float xs = 0, ys = 0, zs = 0;

			switch(quality) {

				case NoiseQuality.Fast:
					xs = (x - (float)x0);
					ys = (y - (float)y0);
					zs = (z - (float)z0);
					break;

				case NoiseQuality.Standard:
					xs = Libnoise.SCurve3(x - (float)x0);
					ys = Libnoise.SCurve3(y - (float)y0);
					zs = Libnoise.SCurve3(z - (float)z0);
					break;

				case NoiseQuality.Best:
					xs = Libnoise.SCurve5(x - (float)x0);
					ys = Libnoise.SCurve5(y - (float)y0);
					zs = Libnoise.SCurve5(z - (float)z0);
					break;
			}//end switch

			// Now calculate the noise values at each vertex of the cube.  To generate
			// the coherent-noise value at the input point, interpolate these eight
			// noise values using the S-curve value as the interpolant (trilinear
			// interpolation.)
			float n0, n1, ix0, ix1, iy0, iy1;

			n0   = GradientNoise3D(x, y, z, x0, y0, z0, seed);
			n1   = GradientNoise3D(x, y, z, x1, y0, z0, seed);
			ix0  = Libnoise.Lerp(n0, n1, xs);

			n0   = GradientNoise3D(x, y, z, x0, y1, z0, seed);
			n1   = GradientNoise3D(x, y, z, x1, y1, z0, seed);
			ix1  = Libnoise.Lerp(n0, n1, xs);
			iy0  = Libnoise.Lerp(ix0, ix1, ys);

			n0   = GradientNoise3D(x, y, z, x0, y0, z1, seed);
			n1   = GradientNoise3D(x, y, z, x1, y0, z1, seed);
			ix0  = Libnoise.Lerp(n0, n1, xs);

			n0   = GradientNoise3D(x, y, z, x0, y1, z1, seed);
			n1   = GradientNoise3D(x, y, z, x1, y1, z1, seed);
			ix1  = Libnoise.Lerp(n0, n1, xs);
			iy1  = Libnoise.Lerp(ix0, ix1, ys);

			return Libnoise.Lerp(iy0, iy1, zs);

		}//end GradientCoherentNoise3D

		/// <summary>
		/// Generates a gradient-noise value from the coordinates of a
		/// three-dimensional input value and the integer coordinates of a
		/// nearby three-dimensional value.
		///
		/// The difference between fx and ix must be less than or equal to one.
		/// The difference between fy and iy must be less than or equal to one.
		/// The difference between fz and iz must be less than or equal to one.
		///
		/// A <i>gradient</i>-noise function generates better-quality noise than a
		/// <i>value</i>-noise function.  Most noise modules use gradient noise for
		/// this reason, although it takes much longer to calculate.
		///
		/// The return value ranges from -1.0 to +1.0.
		///
		/// This function generates a gradient-noise value by performing the
		/// following steps:
		/// - It first calculates a random normalized vector based on the
		///   nearby integer value passed to this function.
		/// - It then calculates a new value by adding this vector to the
		///   nearby integer value passed to this function.
		/// - It then calculates the dot product of the above-generated value
		///   and the floating-point input value passed to this function.
		///
		/// A noise function differs from a random-number generator because it
		/// always returns the same output value if the same input value is passed
		/// to it.
		/// </summary>
		/// <param name="fx">The floating-point x coordinate of the input value</param>
		/// <param name="fy">The floating-point y coordinate of the input value</param>
		/// <param name="fz">The floating-point z coordinate of the input value</param>
		/// <param name="ix">The integer x coordinate of a nearby value</param>
		/// <param name="iy">The integer y coordinate of a nearby value</param>
		/// <param name="iz">The integer z coordinate of a nearby value</param>
		/// <param name="seed">The random number seed</param>
		/// <returns>The generated gradient-noise value.</returns>
		protected float GradientNoise3D(float fx, float fy, float fz, int ix, int iy, int iz, long seed) {
			// Randomly generate a gradient vector given the integer coordinates of the
			// input value.  This implementation generates a random number and uses it
			// as an index into a normalized-vector lookup table.
			long vectorIndex = (
				X_NOISE_GEN * ix
				+ Y_NOISE_GEN * iy
				+ Z_NOISE_GEN * iz
				+ SEED_NOISE_GEN * seed
			) & 0xffffffff;

			vectorIndex ^= (vectorIndex >> SHIFT_NOISE_GEN);
			vectorIndex &= 0xff;

			float xvGradient = _randomVectors[(vectorIndex << 2)];
			float yvGradient = _randomVectors[(vectorIndex << 2) + 1];
			float zvGradient = _randomVectors[(vectorIndex << 2) + 2];

			// Set up us another vector equal to the distance between the two vectors
			// passed to this function.
			float xvPoint = (fx - (float)ix);
			float yvPoint = (fy - (float)iy);
			float zvPoint = (fz - (float)iz);

			// Now compute the dot product of the gradient vector with the distance
			// vector.  The resulting value is gradient noise.  Apply a scaling value
			// so that this noise value ranges from -1.0 to 1.0.
			return ((xvGradient * xvPoint) + (yvGradient * yvPoint) + (zvGradient * zvPoint)) * 2.12f;

		}//end GradientNoise3D

		#endregion

	}//end class

}//end namespace
